#include <cuda_runtime.h>
#include "kuaicu.h"
#include <cassert>
#include <iostream>


#define N 10

namespace kuai { namespace cuda {

__global__ void testTime1(const int list[], const float mem[], float result[], clock_t timer[]) {
	int tid = threadIdx.x;
	int temp[N];
	for (int i = 0; i < N; ++i) {
		temp[i] = list[tid+i];
	}
	timer[tid*2]=clock();
	float sum = 0;
	#pragma unroll 10
	for (int i = 0; i < N; ++i) {
		sum += mem[tid+i];
	}
	timer[tid*2+1]=clock();
	result[tid] = sum;
}

__global__ void testTime2(const int list[], const float mem[], float result[], clock_t timer[]) {
	int tid = threadIdx.x;
	int temp[N];
	for (int i = 0; i < N; ++i) {
		temp[i] = list[tid+i];
	}
	int start = temp[0];
	timer[tid*2]=clock();
	float sum = 0;
	#pragma unroll 10
	for (int i = 0; i < N; ++i) {
		sum += mem[start+i];
	}	
	timer[tid*2+1]=clock();
	result[tid] = sum;
}

__global__ void testTime3(const int list[], const float mem[], float result[], clock_t timer[]) {
	int tid = threadIdx.x;
	int temp[N];
	for (int i = 0; i < N; ++i) {
		temp[i] = list[tid+i];
	}
	timer[tid*2]=clock();
	float sum = 0;
	#pragma unroll 10
	for (int i = 0; i < N; ++i) {
		sum += mem[temp[i]];
	}	
	timer[tid*2+1]=clock();
	result[tid] = sum;
}

int delta(const Array<clock_t>& time) {
	std::vector<clock_t> ticks;
	time.get(ticks);
	return *std::max_element(ticks.begin(), ticks.end())
		- *std::min_element(ticks.begin(), ticks.end());
}

extern void testTime(
		const FloatArray& x, const Array<int> list, 
		FloatArray& result, Array<clock_t>& time)
{
	int d;
	testTime1<<<1, 512>>>(list.at(0), x.at(0), result.at(0), time.at(0));
	d = delta(time);
	std::cout << d << std::endl;
	testTime2<<<1, 512>>>(list.at(0), x.at(0), result.at(0), time.at(0));
	d = delta(time);
	std::cout << d << std::endl;
	testTime3<<<1, 512>>>(list.at(0), x.at(0), result.at(0), time.at(0));
	d = delta(time);
	std::cout << d << std::endl;

}

}}

